package com.sinder.campus_prophet.service.jwgl.impl;

import cc.lyceum.api.thxy.jwgl.ThxyJwgl;
import cc.lyceum.api.thxy.jwgl.pojo.Curriculum;
import cc.lyceum.api.thxy.jwgl.pojo.ExamArrange;
import cc.lyceum.api.thxy.jwgl.pojo.ExamResults;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sinder.campus_prophet.core.global.ResponseMessage;
import com.sinder.campus_prophet.entity.jwgl.*;
import com.sinder.campus_prophet.exception.JwglException;
import com.sinder.campus_prophet.mapper.general.TbWxUserMapper;
import com.sinder.campus_prophet.mapper.jwgl.*;
import com.sinder.campus_prophet.service.jwgl.TbJwglInfoService;
import com.sinder.campus_prophet.service.jwgl.bean.dto.BindJwglDto;
import com.sinder.campus_prophet.service.jwgl.bean.dto.SynJwglDto;
import com.sinder.campus_prophet.service.jwgl.bean.vo.JwglInfoVo;
import com.sinder.campus_prophet.utils.CurrentXqCodeUtils;
import com.sinder.campus_prophet.utils.IsNotExits;
import com.sinder.campus_prophet.utils.RandomColorUtils;
import com.sinder.campus_prophet.utils.TermCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author AS
 * @description 针对表【tb_jwgl_info(用户教务账号密码)】的数据库操作Service实现
 * @createDate 2023-03-15 23:13:21
 */
@Service
@Slf4j
public class TbJwglInfoServiceImpl extends ServiceImpl<TbJwglInfoMapper, TbJwglInfo>
        implements TbJwglInfoService {

    private final ThxyJwgl thxyJwgl;
    private final TbJwglInfoMapper jwglInfoMapper;
    private final TbAchievementMapper achievementMapper;
    private final TbCultureProgramMapper cultureProgramMapper;
    private final TbScheduleMapper scheduleMapper;
    private final TbWxUserMapper wxUserMapper;

    private final TbJwglExamMapper jwglExamMapper;

    public TbJwglInfoServiceImpl(ThxyJwgl thxyJwgl, TbJwglInfoMapper jwglInfoMapper,
                                 TbAchievementMapper achievementMapper, TbCultureProgramMapper cultureProgramMapper,
                                 TbScheduleMapper scheduleMapper, TbWxUserMapper wxUserMapper, TbJwglExamMapper jwglExamMapper) {
        this.thxyJwgl = thxyJwgl;
        this.jwglInfoMapper = jwglInfoMapper;
        this.achievementMapper = achievementMapper;
        this.cultureProgramMapper = cultureProgramMapper;
        this.scheduleMapper = scheduleMapper;
        this.wxUserMapper = wxUserMapper;
        this.jwglExamMapper = jwglExamMapper;
    }

    /**
     * 数据同步 同步教务系统数据/课表数据/绩点数据
     *
     * @param synJwglDto openId: 用户标识， sing：用户签名，暂定为sinder@1021的DES加密字符串
     * @return
     */
    @Async("taskExecutor")
    @Override
    public ResponseMessage synJwglData(SynJwglDto synJwglDto, ThxyJwgl jwgl) {
        log.info(Thread.currentThread().getThreadGroup() + "--------" + Thread.currentThread().getName());
        String openId = synJwglDto.getOpenId();
        // 数据同步开始时间
        long start = System.currentTimeMillis();
        // 获取用户标识
        String userCode = wxUserMapper.getUserCode(openId);
        // 1：登录教务系统
        try {
            // 统一新建时间
            Date date = new Date();
            // 根据入学年份获取四年学期参数 202001 == 大一(上) -- 入学年份插入教务信息表
            // 入学年份重新获取
            String rxnf = jwgl.getStudentInfo().getRxnf(); // 获取入学年份
            jwglInfoMapper.setRxnfByWxOpenIdInt(openId, rxnf);
            // 个人学期参数列表
            List<TermCodeUtils.YermCode> yermCodeList = TermCodeUtils.getTermCode(rxnf);
            // 2：获取成绩信息 -- 每个人共有八个学期 -- 数据同步前先清空相关用户旧数据
            QueryWrapper<TbAchievement> achievementDelQuery = new QueryWrapper<>();
            achievementDelQuery.eq("wx_open_id", openId);
            int achDelRow = achievementMapper.delete(achievementDelQuery);
            log.info("----已清空用户openId为：{}的成绩信息{}条数据，正在同步新数据----", openId, achDelRow);
            for (TermCodeUtils.YermCode yerm : yermCodeList) {
                List<ExamResults> examList = jwgl.getExamResults(yerm.getCode());
                // 无数据则不进行处理
                if (examList.size() == 0) {
                    continue;
                }
                // 数据处理
                List<TbAchievement> achievementList = examList.stream().map(item -> {
                    TbAchievement achievement = new TbAchievement();
                    BeanUtils.copyProperties(item, achievement);
                    achievement.setSynTime(date);
                    achievement.setCreateTime(date);
                    achievement.setWxOpenId(openId);
                    return achievement;
                }).collect(Collectors.toList());
                // 批量入库
                achievementMapper.insertBatch(achievementList);
            }
            // 3：获取课表 按学期代码和周数全量同步(正常一学期20周) -- 数据同步前先清空用户旧数据(只保留一个学期课表)
            // 获取本学期代码值
            String xqCode = CurrentXqCodeUtils.getCurrentXqCode();
            QueryWrapper<TbSchedule> scheduleDelQuery = new QueryWrapper<>();
            scheduleDelQuery.eq("wx_open_id", openId);
            int schDelRow = scheduleMapper.delete(scheduleDelQuery);
            log.info("----已清空用户openId为：{}的课表信息{}条数据，正在同步新数据----", openId, schDelRow);
            for (int i = 1; i <= 20; i++) {
                List<Curriculum> curriculumList = jwgl.getSelfCurriculum(xqCode, String.valueOf(i));
                if (curriculumList.size() == 0) {
                    continue;
                }
                List<TbSchedule> scheduleList = curriculumList.stream().map(item -> {
                    TbSchedule schedule = new TbSchedule();
                    BeanUtils.copyProperties(item, schedule);
                    // 课表同步为有课
                    schedule.setType(true);
                    schedule.setWxOpenId(openId);
                    // 添加用户标识
                    schedule.setUserCode(userCode);
                    schedule.setSynTime(date);
                    schedule.setBgColor(RandomColorUtils.getColor());
                    return schedule;
                }).collect(Collectors.toList());
                // 批量入库
                scheduleMapper.insertBatch(scheduleList);
            }
            // 4：获取考试安排信息 -- 后续通过管理平台批量同步
            // 当前学期参数 因为考试信息只需要当前的才有用
//            String currentCode = TermCodeUtils.getCurrentCode(rxnf);
//            List<ExamArrange> examList = jwgl.getExamArrange(currentCode);
//            // 有的人没有考试 -- 或者考试安排还没有出
//            if (examList.size() > 0 ) {
//                // 处理教务考试安排数据
//                List<TbJwglExam> jwglExamList = examList.stream().map(item -> {
//                    TbJwglExam tbJwglExam = new TbJwglExam();
//                    BeanUtils.copyProperties(item, tbJwglExam);
//                    tbJwglExam.setXqdm(currentCode);
//                    tbJwglExam.setSynTime(new Date());
//                    tbJwglExam.setOpenId(openId);
//                    return tbJwglExam;
//                }).collect(Collectors.toList());
//                // 批量入库
//                jwglExamMapper.insertBatch(jwglExamList);
//            }
            // 5：获取培养方案数据 -- 培养方案数据暂时不开放
//            Map<String, String> cultureProgram = jwgl.getStudyStatus();
//            TbCultureProgram cultureProgramEntity = JSON.parseObject(JSON.toJSONString(cultureProgram), TbCultureProgram.class);
            // 执行更新，数据不存在则插入数据
//            QueryWrapper<TbCultureProgram> cultureProgramQuery = new QueryWrapper<>();
//            cultureProgramQuery.eq("wx_open_id", openId);
//            cultureProgramEntity.setWxOpenId(openId);
//            cultureProgramEntity.setSynTime(date);
            // 处理一下数据
//            cultureProgramEntity.setTjmc1(StringUtils.substringBefore(cultureProgramEntity.getTjmc1(), "["));
//            int cultureRow = cultureProgramMapper.update(cultureProgramEntity, cultureProgramQuery);
//            if (cultureRow == 0) {
//                cultureProgramEntity.setCreateTime(date);
//                cultureProgramMapper.insert(cultureProgramEntity);
//            }
        } finally {
            // 结束后退出登录
            if (jwgl != null) {
                jwgl.logout();
            }
        }
        // 数据同步结束时间
        long end = System.currentTimeMillis();
        log.info("教务数据已同步，共耗时：" + (end-start) / 1000 + "s" );
        return ResponseMessage.createBySuccessMessage("教务数据已同步，共耗时：" + (end-start) / 1000 + "s");
    }

    /**
     * 绑定教务系统账号
     *
     * @param bindJwgl
     * @return
     */
    @Override
    public boolean bindJwgl(BindJwglDto bindJwgl) {
        // 判断是否已经绑定
        QueryWrapper<TbJwglInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("wx_open_id", bindJwgl.getWxOpenId());
        List<TbJwglInfo> tbJwglInfo = jwglInfoMapper.selectList(queryWrapper);
        if (tbJwglInfo.size() >= 1) {
            return false;
        }
        // 尝试登录 失败响应
        try {
            String msg = thxyJwgl.login(bindJwgl.getJwglAccount(), bindJwgl.getJwglPassword());
            if (!msg.equals("success")) {
                log.warn(msg);
                throw new JwglException(msg + "==>" + "请移步修改密码");
            }
            // 在保存的时候就填入rxnf
            String rxnf = thxyJwgl.getStudentInfo().getRxnf();
            TbJwglInfo jwglInfo = new TbJwglInfo();
            BeanUtils.copyProperties(bindJwgl, jwglInfo);
            jwglInfo.setRxnf(rxnf);
            jwglInfo.setCreateTime(new Date());
            jwglInfo.setUpdateTime(new Date());

            int row = jwglInfoMapper.ignoreInsert(jwglInfo);
            return row > 0;
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询教务系统账号密码
     *
     * @param openId
     * @return
     */
    @Override
    public ResponseMessage getJwglInfo(String openId) {
        JwglInfoVo jwglInfoVo = jwglInfoMapper.getJwglInfo(openId);
        if (jwglInfoVo == null) {
            throw new NullPointerException("用户不存在，请联系管理员");
        }
        return ResponseMessage.createBySuccess("教务信息", jwglInfoVo);
    }

    /**
     * 更新绑定教务系统账号密码
     *
     * @param bindJwgl
     * @return
     */
    @Override
    public boolean bindUpJwgl(BindJwglDto bindJwgl) {
        try {
            JwglInfoVo jwglInfoVo = jwglInfoMapper.getJwglInfo(bindJwgl.getWxOpenId());
            if (jwglInfoVo == null) {
                throw new NullPointerException("用户不存在，请联系管理员");
            }
            String msg = thxyJwgl.login(bindJwgl.getJwglAccount(), bindJwgl.getJwglPassword());
            if (!msg.equals("success")) {
                log.warn(msg);
                throw new JwglException(msg + "==>" + "请移步修改密码");
            }
            TbJwglInfo jwglInfo = new TbJwglInfo();
            jwglInfo.setJwglAccount(bindJwgl.getJwglAccount());
            jwglInfo.setJwglPassword(bindJwgl.getJwglPassword());
            jwglInfo.setUpdateTime(new Date());

            QueryWrapper<TbJwglInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("wx_open_id", jwglInfoVo.getWxOpenId());
            int row = jwglInfoMapper.update(jwglInfo, queryWrapper);
            return row > 0;
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 校验是否登录
     * @param openId
     * @return
     */
    @Override
    public ThxyJwgl checkJwglLogin(String openId, HttpServletRequest request) {
        // 查询用户教务系统账号密码
        JwglInfoVo jwglInfoVo = jwglInfoMapper.getJwglInfo(openId);
        if (jwglInfoVo == null) {
            throw new JwglException("请先绑定教务信息");
        }

        String jwglAccount = jwglInfoVo.getJwglAccount();
        String jwglPassword = jwglInfoVo.getJwglPassword();
        String msg = null;
        try {
            msg = thxyJwgl.login(jwglAccount, jwglPassword);
            if (!msg.equals("success")) {
                log.warn(msg);
                throw new JwglException(msg);
            }
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage());
            throw new JwglException(e.getMessage());
        }
        return thxyJwgl;
    }
}




